import {
  getInvolvedMeshes,
  getMeshRect,
  getMeshVerts,
  subtractAreaByHoles,
  subtractHoleToArea,
} from './EditWorkArea.js';
import UndoType from './undo/UndoType.js';
import {bufferAttributeToVectors} from "../lib/util/StaticMethods.js";

// 不可喷涂区编辑，负责新增和删除
export default class EditHoleArea {
  world3d;

  constructor(world3d) {
    this.world3d = world3d;
  }

  /**
   *  不可喷涂区域删除或者发生形变后，更新相应的工作区.
   *  注意1：如果正在删除孔洞，调用必须确保 store.holeMeshes 数组中不包含 输入：holeMesh
   *  注意2：如果孔洞发生形变，计算 involvedMeshes 时，额外需要形变发生前的 workArea.oldLocalBox3 属性
   * @param {HoleMesh} holeMesh
   * @param {boolean} removingHole  true: 正在删除孔洞， false: 孔洞发生形变
   */
  updateWorkAreaByHole(holeMesh, removingHole) {
    const holeArea = holeMesh.vo;
    const holeBox3 = holeArea.localBox3;
    const oldHoleBox3 = holeArea.oldLocalBox3;
    const store = this.world3d.store;
    let involvedMeshes;
    if (removingHole) {
      involvedMeshes = getInvolvedMeshes(
        holeArea.createPlane(),
        store.areaMeshes,
        [holeBox3],
      );
    } else {
      // 孔洞发生形变后，额外需要考虑 workArea.oldLocalBox3 属性
      involvedMeshes = getInvolvedMeshes(
        holeArea.createPlane(),
        store.areaMeshes,
        [holeBox3, oldHoleBox3],
      );
    }

    if (!involvedMeshes.length) {
      // 删除的孔洞 或 形变的孔洞，不会影响任何工作区
      return { removed: [], added: [] };
    }
    const removed = [];
    const added = [];
    involvedMeshes.forEach((mesh) => {
      const oldVertObj = mesh.vo.verts.slice()
      // mesh.vo.resetShapeToBoundingRect()
      // this._prepare4HoleUpdate(mesh);
      const obj = subtractAreaByHoles(store.holeMeshes, mesh);
      removed.push(...obj.removed);
      added.push(...obj.added);
      mesh.vo.verts = oldVertObj;
    });
    removed.forEach((mesh) => mesh.removeFromParent());
    added.forEach((mesh) => this.world3d.scene.add(mesh));
    let workAreas = [];
    store.areaMeshes.forEach((mesh) => {
      if (!removed.includes(mesh)) {
        workAreas.push(mesh);
      }
    });
    workAreas = workAreas.concat(added);
    store.areaMeshes.length = 0;
    store.areaMeshes.push(...workAreas);
    workAreas.forEach(areaMesh => {
      areaMesh.vo.computeArea();
      areaMesh.vo.initWidthAndHeight();
    });
    return { removed, added };
  }

  // 在3d场景中选中 不可喷涂区 按键盘 DEL 删除
  removeHoleMesh() {
    const store = this.world3d.store;
    const holeMesh = store.pickingHole();
    if (!holeMesh) {
      return false;
    }
    const index = store.holeMeshes.indexOf(holeMesh);
    store.holeMeshes.splice(index, 1);
    holeMesh.removeFromParent();
    store.resetPicking(null);
    // const {removed, added} = this.updateWorkAreaByHole(holeMesh, true)
    const ctx = {
      scene: this.world3d.scene,
      removedArea: [], // removed,
      addedArea: [], // added,
      arrArea: store.areaMeshes,
      arrHole: store.holeMeshes,
      holeMesh: holeMesh,
    };
    this.world3d.editRecord.addAction(UndoType.removeHole, ctx);
    this.world3d.editorContentChanged = true;
    return true;
  }

  pointerDown(event) {
    if (event.button === 2) {
      // mouse right button down
      return false;
    }
    const store = this.world3d.store;
    if (store.stateAddingHole && (store.pickingArea() || store.pickingTile())) {
      // 新增孔洞，可以在工作区和b3dms瓦片模型上新增
      store.initNewHoleMesh();
    }
  }

  pointerMove(event) {
    if (event.button === 2) {
      // mouse right button down
      return;
    }
    const store = this.world3d.store;
    if (store.stateAddingHole && store.addingHoleMesh) {
      // 正在画矩形 新增孔洞
      store.updateAddingHoleRect();
    }
  }

  pointerUpUnmoved(event) {
    const store = this.world3d.store;
    store.clearAddingHoleMesh();
    if (event.button === 2) {
      // mouse right button down
      if (store.stateAddingHole) {
        store.freeState();
        this.world3d.switchCamera(false);
      }
    }
  }

  pointerUpMoved(event) {
    if (event.button === 2) {
      // mouse right button down
      return;
    }
    const store = this.world3d.store;
    const holeMesh = store.addingHoleMesh;
    if (store.stateAddingHole && holeMesh) {
      // 新增孔洞时，画矩形完毕
      const holeArea = holeMesh.vo;
      if (holeArea.area < 0.01) {
        store.clearAddingHoleMesh();
        return;
      }
      if (store.usingPlaneRef) {
        const vectors = bufferAttributeToVectors(holeMesh.geometry.attributes.position);
        holeArea.toOtherSpace(store.getFacing().planeMat0, store.getFacing().planeMatInv0, vectors)
      } else {
        holeArea.verts = getMeshVerts(holeMesh);
        holeArea.localBox3 = getMeshRect(holeArea.verts[0]);
      }
      const { removed, added } = subtractHoleToArea(
        store.areaMeshes,
        holeMesh,
      );
      removed.forEach((mesh) => mesh.removeFromParent());
      added.forEach((mesh) => this.world3d.scene.add(mesh));
      const ctx = {
        scene: this.world3d.scene,
        removedArea: removed,
        addedArea: added,
        arrArea: store.areaMeshes,
        arrHole: store.holeMeshes,
        holeMesh: holeMesh,
      };
      this.world3d.editRecord.addAction(UndoType.addHole, ctx);

      store.addHoleMeshToStore();
    }
  }
}
